#pragma once

#include <vector>

#include <semaphore.h>
#include <pthread.h>

#ifdef __TEST__
template<class T, size_t MAX = 64 / sizeof(T)>
#else
template<class T, size_t MAX = 1024 / sizeof(T)>
#endif
class RingQueue
{
    typedef T value_type;
    typedef RingQueue<value_type, MAX> self;
public:
    RingQueue()
    {
        _v.resize(MAX);
        sem_init(&_p_sem, 0, MAX);
        sem_init(&_c_sem, 0, 0);
        pthread_mutex_init(&_c_mtx, nullptr);
        pthread_mutex_init(&_p_mtx, nullptr);
    }
    RingQueue(const self&) = delete;
    self& operator=(const self&) = delete;

    value_type pop()
    {
        sem_wait(&_c_sem);      //先申请信号量,提高效率
        pthread_mutex_lock(&_c_mtx);
        value_type ret = _v[_c_step];
        _c_step = (_c_step + 1) % MAX;
        pthread_mutex_unlock(&_c_mtx);
        sem_post(&_p_sem);
        return ret;
    }

    template<class... Args>
    void emplace(Args&&... args)
    {
        sem_wait(&_p_sem);
        pthread_mutex_lock(&_p_mtx);
        _v[_p_step] = value_type(args...);
        _p_step = (_p_step + 1) % MAX;
        pthread_mutex_unlock(&_p_mtx);
        sem_post(&_c_sem);
    }
    void push(const value_type& val)
    {
        emplace(val);
    }
    void push(value_type&& val)
    {
        emplace(std::forward<value_type>(val));
    }

    ~RingQueue()
    {
        sem_destroy(&_c_sem);
        sem_destroy(&_p_sem);
        pthread_mutex_destroy(&_c_mtx);
        pthread_mutex_destroy(&_p_mtx);
    }
private:
    std::vector<value_type> _v;
    size_t _c_step = 0; //begin
    size_t _p_step = 0; //end
    
    sem_t _c_sem;       //data_sem
    sem_t _p_sem;       //space_sem

    pthread_mutex_t _c_mtx;
    pthread_mutex_t _p_mtx;
};